/*
 * DocsPreferencePage.java
 * 
 * Copyright (c) 2007
 * 
 * Licensed under the Apache License, Version 2.0 (the "License");
 * you may not use this file except in compliance with the License.
 * You may obtain a copy of the License at
 *
 *     http://www.apache.org/licenses/LICENSE-2.0
 * 
 * Unless required by applicable law or agreed to in writing, software
 * distributed under the License is distributed on an "AS IS" BASIS,
 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
 * See the License for the specific language governing permissions and
 * limitations under the License.
 */

package org.dcarew.googledocs.preferences;

import org.dcarew.googledocs.DocsCredentials;
import org.dcarew.googledocs.DocsPlugin;
import org.dcarew.googledocs.utils.DocsUtils;
import org.eclipse.jface.preference.PreferencePage;
import org.eclipse.swt.SWT;
import org.eclipse.swt.custom.BusyIndicator;
import org.eclipse.swt.events.ModifyEvent;
import org.eclipse.swt.events.ModifyListener;
import org.eclipse.swt.events.SelectionAdapter;
import org.eclipse.swt.events.SelectionEvent;
import org.eclipse.swt.layout.GridData;
import org.eclipse.swt.layout.GridLayout;
import org.eclipse.swt.widgets.Button;
import org.eclipse.swt.widgets.Composite;
import org.eclipse.swt.widgets.Control;
import org.eclipse.swt.widgets.Display;
import org.eclipse.swt.widgets.Group;
import org.eclipse.swt.widgets.Label;
import org.eclipse.swt.widgets.Text;
import org.eclipse.ui.IWorkbench;
import org.eclipse.ui.IWorkbenchPreferencePage;

import com.google.gdata.client.spreadsheet.SpreadsheetService;
import com.google.gdata.util.AuthenticationException;

/**
 * The preference page or the Google Docs plugin. This page allows the user to enter their Google
 * Account information.
 * 
 * @author Devon Carew
 */
public class DocsPreferencePage
	extends PreferencePage
	implements IWorkbenchPreferencePage
{
	private Button 	testAccountButton;
	private Text	userNameText;
	private Text	passwordText;
	
	
	public DocsPreferencePage()
	{
		setPreferenceStore(DocsPlugin.getDefault().getPreferenceStore());
		setDescription("Enter your Google Account authorization information. If you do not have an account, you can create one at http://docs.google.com.");
		
		noDefaultAndApplyButton();
	}
	
	public void init(IWorkbench workbench)
	{
		
	}
	
	protected Control createContents(Composite prefPageParent)
	{
		setTitle("Google Docs && Spreadsheets");
		
		Composite parent = new Composite(prefPageParent, SWT.NONE);
		GridLayout parentLayout = new GridLayout();
		parentLayout.marginWidth = 0;
		parentLayout.marginHeight = 0;
		parent.setLayout(parentLayout);
		
		Group group = new Group(parent, SWT.NONE);
		group.setText("Authorization");
		GridData gridData = new GridData(GridData.FILL_HORIZONTAL);
		gridData.verticalIndent = 15;
		group.setLayoutData(gridData);
		group.setLayout(new GridLayout(2, false));
		
		// Account email
		Label label = new Label(group, SWT.NONE);
		label.setText("Account Email:");
		
		userNameText = new Text(group, SWT.SINGLE | SWT.BORDER);
		userNameText.setTextLimit(100);
		userNameText.setLayoutData(new GridData(GridData.FILL_HORIZONTAL));
		userNameText.addModifyListener(new ModifyListener() {
			public void modifyText(ModifyEvent e) {
				updateTestButton();
			}
		});
		
		// Password
		label = new Label(group, SWT.NONE);
		label.setText("Password:");
		
		passwordText = new Text(group, SWT.SINGLE | SWT.PASSWORD | SWT.BORDER);
		passwordText.setTextLimit(100);
		passwordText.setLayoutData(new GridData(GridData.FILL_HORIZONTAL));
		passwordText.addModifyListener(new ModifyListener() {
			public void modifyText(ModifyEvent e) {
				updateTestButton();
			}
		});
		
		updateFromPreferences();
		
		return parent;
	}
	
	protected void contributeButtons(Composite parent)
	{
		super.contributeButtons(parent);
		
		((GridLayout) parent.getLayout()).numColumns++;
		
		testAccountButton = new Button(parent, SWT.PUSH);
		testAccountButton.setText("Test Account");
		testAccountButton.addSelectionListener(new SelectionAdapter() {
			public void widgetSelected(SelectionEvent event) {
				performAccountTest();
			}
		});
		
		updateTestButton();
	}
	
	private void updateFromPreferences()
	{
		DocsCredentials userCredentials = DocsPlugin.getUserCredentials();
		
		if (userCredentials != null)
		{
			userNameText.setText(userCredentials.getUserName());
			passwordText.setText(userCredentials.getPassword());
		}
	}
	
	public boolean performOk()
	{
		DocsPlugin.setUserCredentials(userNameText.getText().trim(), passwordText.getText().trim());
		
		return true;
	}
	
	private void updateTestButton()
	{
		if (testAccountButton == null || testAccountButton.isDisposed())
			return;
		
		clearMessage();
		
		String user = userNameText.getText();
		String pass = passwordText.getText();
		
		if (user == null || user.trim().length() == 0)
			testAccountButton.setEnabled(false);
		else if (pass == null || pass.trim().length() == 0)
			testAccountButton.setEnabled(false);
		else
			testAccountButton.setEnabled(true);
	}
	
	private void performAccountTest()
	{
		final String user = userNameText.getText().trim();
		final String pass = passwordText.getText().trim();
		
		clearMessage();
		
		BusyIndicator.showWhile(getShell().getDisplay(), new Runnable() {
			public void run()
			{
				try
				{
					testLogin(user, pass);
					
					setMessage("Authorization succeeded.", INFORMATION);
				}
				catch (AuthenticationException authException)
				{
					setMessage(authException.getMessage(), ERROR);
				}
				
				clearMessageDelayed(3000);
			}
		});
	}
	
	private void clearMessage()
	{
		if (testAccountButton != null && !testAccountButton.isDisposed())
		{
			setMessage(null);
		}
	}
	
	private void clearMessageDelayed(final int millis)
	{
		final String 	oldMessage = getMessage();
		final Display 	display = getShell().getDisplay();
		
		new Thread(new Runnable() {
			public void run()
			{
				DocsUtils.sleepMillis(millis);
				
				display.asyncExec(new Runnable() {
					public void run()
					{
						if (DocsUtils.safeEquals(oldMessage, getMessage()))
						{
							clearMessage();
						}
					}
				});
			}
		}).start();
	}
	
	private static void testLogin(String userName, String password)
		throws AuthenticationException
	{
		SpreadsheetService service = new SpreadsheetService(DocsPlugin.APPLICATION_NAME);
		
		service.setUserCredentials(userName, password);
	}
	
}
